package com.gitee.base.modules.core.controller;

import com.gitee.base.modules.BaseController;
import com.gitee.base.modules.core.model.SysPermission;
import com.gitee.base.modules.core.model.SysRole;
import com.gitee.base.modules.core.service.ISysPermissionService;
import com.gitee.base.modules.core.service.ISysRoleService;
import com.gitee.base.security.permission.Permission;
import com.gitee.base.security.permission.PermissionResolver;
import com.gitee.base.security.permission.annotation.RequiresPermissionsDesc;
import com.gitee.base.utils.JsonVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.ui.ModelMap;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.validation.constraints.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Controller
@RequestMapping("/core/role")
@Validated
public class CoreRoleController extends BaseController {
    @Autowired
    private ISysRoleService sysRoleService;

    @RequiresPermissionsDesc(folder = "系统管理",menu = "角色管理",button = "查看",page = true)
    @RequiresPermissions("core:role:list")
    @GetMapping("/list")
    public String list(ModelMap modelMap){
        modelMap.put("roleList", this.sysRoleService.list());
        return "core/role/list";
    }

    @RequiresPermissionsDesc(folder = "系统管理",menu = "角色管理",button = "添加")
    @RequiresPermissions("core:role:add")
    @GetMapping("/add")
    public String add(ModelMap modelMap){
        List<Permission> curUserHasRolePermList = getCurUserHasRolePerm();
        List<String> waitAuthRolePermList = getWaitAuthRolePerm(null);
        modelMap.put("curUserHasRolePermList",curUserHasRolePermList);
        modelMap.put("waitAuthRolePermList",waitAuthRolePermList);
        return "core/role/addOrEdit";
    }

    @RequiresPermissions("core:role:add")
    @PostMapping("/save")
    @ResponseBody
    @Transactional
    public JsonVo save(@Validated SysRole sysRole, @NotEmpty(message = "至少要赋予一个权限") String[] permissions){
        this.sysRoleService.save(sysRole);

        this.sysPermissionService.remove(new LambdaQueryWrapper<SysPermission>().eq(SysPermission::getRoleId,sysRole.getId()));

        List<SysPermission> sysPermissions = new ArrayList<>();
        for(String permission:permissions){
            if(StringUtils.isBlank(permission)) continue;
            sysPermissions.add(SysPermission.builder().roleId(sysRole.getId()).permission(permission).build());
        }
        this.sysPermissionService.saveBatch(sysPermissions);

        return JsonVo.success();
    }

    @RequiresPermissionsDesc(folder = "系统管理",menu = "角色管理",button = "修改")
    @RequiresPermissions("core:role:edit")
    @GetMapping("/edit")
    public String edit(ModelMap modelMap, @NotNull Integer id){
        modelMap.put("role",this.sysRoleService.getById(id));
        List<Permission> curUserHasRolePermList = getCurUserHasRolePerm();
        List<String> waitAuthRolePermList = getWaitAuthRolePerm(id);
        modelMap.put("curUserHasRolePermList",curUserHasRolePermList);
        modelMap.put("waitAuthRolePermList",waitAuthRolePermList);
        return "core/role/addOrEdit";
    }

    @RequiresPermissions("core:role:edit")
    @PostMapping("/update")
    @ResponseBody
    @Transactional
    public JsonVo update(@Validated SysRole sysRole, @NotEmpty(message = "至少要赋予一个权限") String[] permissions){
        this.sysRoleService.updateById(sysRole);

        if(sysRole.getId()>1){
            //超级管理员不允许修改权限
            this.sysPermissionService.remove(new LambdaQueryWrapper<SysPermission>().eq(SysPermission::getRoleId,sysRole.getId()));

            List<SysPermission> sysPermissions = new ArrayList<>();
            for(String permission:permissions){
                if(StringUtils.isBlank(permission)) continue;
                sysPermissions.add(SysPermission.builder().roleId(sysRole.getId()).permission(permission).build());
            }
            this.sysPermissionService.saveBatch(sysPermissions);
        }

        return JsonVo.success();
    }

    @RequiresPermissionsDesc(folder = "系统管理",menu = "角色管理",button = "删除")
    @RequiresPermissions("core:role:delete")
    @PostMapping("/delete")
    @ResponseBody
    public JsonVo delete(@NotNull @Min(value = 2, message = "此条不可删除") Integer id){
        this.sysRoleService.removeById(id);
        return JsonVo.success();
    }

    private List<Permission> getCurUserHasRolePerm(){
        String roleIds = getLoginUser().getRoleIds();
        if(StringUtils.isNotBlank(roleIds)){
            int[] roleIdArray = Stream.of(roleIds.split(",")).distinct().mapToInt(Integer::valueOf).toArray();
            List<Permission> permissionList = this.permissionResolver.permissionsByRoleIds(roleIdArray);
            if(permissionList!=null) return permissionList;
        }
        return Collections.EMPTY_LIST;
    }

    private List<String> getWaitAuthRolePerm(Integer roleId){
        if(roleId==null) return Collections.EMPTY_LIST;
        List<Permission> permissionList = this.permissionResolver.permissionsByRoleIds(roleId);
        if(permissionList!=null) {
            List<Permission> targetPermissionList = new ArrayList<>();
            for(Permission folder:permissionList){
                if(StringUtils.isNotBlank(folder.getPermission())) targetPermissionList.add(folder);
                if(folder.getChildren()==null||folder.getChildren().isEmpty()) continue;
                for(Permission menu:folder.getChildren()){
                    if(StringUtils.isNotBlank(menu.getPermission())) targetPermissionList.add(menu);
                    if(menu.getChildren()==null||menu.getChildren().isEmpty()) continue;
                    targetPermissionList.addAll(menu.getChildren());
                }
            }
            return targetPermissionList.stream().map(Permission::getPermission).collect(Collectors.toList());
        }
        return Collections.EMPTY_LIST;
    }

    @Autowired
    private PermissionResolver permissionResolver;
    @Autowired
    private ISysPermissionService sysPermissionService;
}
